'As you probably already know; AmigaBasic SUCKS! It can't handle structures. 'Yet another shoddy Microsoft product. Actually, this is about the fifth 'basic program I've ever written. The other four were done in a 15 week 'course some years back in college. I'm an assembly programmer, and usually 'I don't touch this crap, but someone had to write an example. The code is 'probably not too efficient, but it's the first basic program I've written 'in years, the first in AmigaBasic, and was done in about 2 hours (I had to 'read the AmigaBasic instruction book. Really.) I cannot begin to tell you 'how excruciating the AmigaBasic editor is to an assembly programmer. CLS LOCATE 1,8 PRINT "Demo AmigaBasic program using the FileIO requester library." LOCATE 2,11 PRINT "Literally hacked together by Jeff Glatt (dissidents)" DEFLNG a-Z 'IMPORTANT! All variables are longs (for the library calls) 'requester.bmap and exec.bmap must be in the current directory LIBRARY "requester.library" LIBRARY "exec.library" DECLARE FUNCTION AllocMem() LIBRARY DECLARE FUNCTION DoFileIOWindow() LIBRARY 'These are in the FileIO lib. DECLARE FUNCTION GetFullPathname() LIBRARY 'Other functions in the lib do DECLARE FUNCTION GetFileIO() LIBRARY 'not return values, and so do not DECLARE FUNCTION AutoFileMessage() LIBRARY 'need declaring DECLARE FUNCTION AutoPrompt3() LIBRARY DECLARE FUNCTION TypeFilename() LIBRARY DECLARE FUNCTION UserEntry() LIBRARY DECLARE FUNCTION PromptUserEntry() LIBRARY DECLARE FUNCTION GetRawkey() LIBRARY DECLARE FUNCTION DecodeRawkey() LIBRARY 'First we must get a buffer for the pathname. The FileIO's DoFileIOWindow() 'will copy the complete pathname there. The complete path looks just like 'a CLI line: ' Diskname:TopDrawer/SubDrawer...etc...BottomDrawer/Filename 'Of course, the user may only select a disk or drawer, but no filename, and 'so the final "/Filename" will not be there. Also, the Filename might not 'be in any drawers, and so it will appear directly after the diskname. If 'this format looks weird to you, you need to learn about the CLI. 'We'll get our buffer from Exec via AllocMem(). MEMF.PUBLIC = 1 : MEMF.CLEAR = 65536 : BUFSIZE = 202 BufferPtr=AllocMem(BUFSIZE,MEMF.PUBLIC+MEMF.CLEAR) 'A buffer to copy the pathname to IF BufferPtr = 0 THEN GOTO NoMem1 'Now we need to get a buffer if we want to allow the user to utilize the 'extention match feature. BUFSIZE2 = 24 ExtPtr=AllocMem(BUFSIZE2,MEMF.PUBLIC+MEMF.CLEAR) IF ExtPtr = 0 THEN GOTO NoMem2 FileIO=GetFileIO(0) 'Get the address of the FileIO structure 'Actually you don't need to pass the 0, but AmigaBasic seems to want something... IF FileIO = 0 THEN GOTO CloseUp1 '0 means that you don't have a FileIO. 'Set the FileIO's Buffer field to our allocated PathBuffer's address POKEL FileIO+248,BufferPtr POKEL FileIO+222,ExtPtr 'Set the address of the extention string 'Set the title that will displayed in the FileIO window. This can be changed 'for each call so that you might have the title read "Save File" during a 'save routine, for example. WindowTitle$ = "FileIO Basic Example" POKEL FileIO+244,SADD(WindowTitle$) 'Set the fore pen, back pen, and draw mode for title bar routines to some 'defaults. We always need to do this in case the requester is in use by 'another program and we get automatic title bar file entry. To demo this, 'run this program twice simultaneously with one of them having the file 'requester displayed. Note that the title bar entry appears in the 2nd 'window. This is because only 1 task can be displaying the FileIO requester 'at a time. Other simultaneous calls get redirected to the title bar entry. POKE FileIO+261,1 'JAM2 DrawMode POKE FileIO+262,1 'PenA = Color1 POKE FileIO+263,0 'PenB = Color0 DIM Pathname$(202) DIM Filename$(30) DIM VolName$(30) DIM DrawerName$(132) Again: 'First I'll demo 2 things you can do with the Flags field of the FileIO. The 'FileIO is a structure, and our variable name FileIO is just the start (base) 'of that structure (block of memory). We can access any field of the FileIO 'by PEEKing and POKEing various fields. You should POKE a value into the 'FileIO, and retrieve a value by PEEKing. Some fields are larger than 1 byte 'and you must use PEEKW, PEEKL, POKEW, POKEL. You need to know how far away 'the field is from the base of the structure. The flags field is one byte 'away, so to access it we PEEK or POKE to FileIO+1. The previous initialization 'we did for the window title was at an offset of 244 from the base, and was 'a LONGWORD (4 bytes). That's why I added the L to POKE. 'Since the user can always set these features up for himself via the 10 'functions keys (see the doc), normally you wouldn't bother with the Flags 'field unless you had something particular in mind...but for a demo... LOCATE 3,1 'See if the user wants only those filenames that end in a certain extention 'Actually, the user can change this string after the requester opens via F4 'so you should never assume that the returned filename will indeed end in 'this string. If the user changes it, he probably knows what he's doing. Ha, ha. INPUT "Do you want only those filenames with a certain extention (y or n)";Ans$ IF Ans$ <> "y" THEN GOTO SkipExt INPUT "Type the extention, 14 chars max (i.e., .device)";EXT$ extsize=LEN(EXT$) IF extsize = 0 THEN GOTO SkipExt IF extsize > 13 THEN GOTO SkipExt 'too long 'Enable the extention match feature of the FileIO POKE FileIO+1,4 'Turn on extention match feature only POKEW FileIO+226,extsize 'Get the length of the string 'Copy the user string to the extention buffer EXT$ = UCASE$(EXT$) 'must be upper case FOR i = 0 TO 13 char$ = EXT$(i) value = ASC(char$) POKE(BufferPtr+i),value NEXT i POKE(BufferPtr+14),0 GOTO DoIO SkipExt: 'Otherwise, at least suppress the .info files POKE FileIO+1,128 DoIO: Result=DoFileIOWindow(FileIO,0) 'do the FileIO selection on WB screen IF Result <> -1 THEN GOTO CheckError '-1 means the user selected CANCEL. message$ = "User selected CANCEL."+CHR$(0) CALL AutoMessageLen(SADD(message$),WINDOW(7),21) '21 is the number of chars in Message$ not counting the CHR$(0) GOTO CloseUp2 CheckError: '0 means the FileIO window couldn't open due (probably due to lack of mem). 'Too bad! You'll have to get the filename some other way. Maybe an INPUT statement? IF Result <> 0 THEN GOTO GotPathname 'Message number 0 in the FileIO lib says "Out of memory for this operation" Result=AutoFileMessage(0,WINDOW(7)) INPUT "Type path: ";Pathname$ CALL ParseString(FileIO,SADD(Pathname$)) GOTO CopyFN GotPathname: 'We got a selection from the user! 'Now, our PathBuffer$ has the complete pathname. The FileIO's Filename 'buffer has just the Filename separated from the disk and drawer names '(which are also separated into their own FileIO buffers). Let's copy out 'each of these buffers so that we can print the separate pieces, plus copy 'the complete path. Pathname$ = "" FOR i = 0 TO 202 value = PEEK(BufferPtr+i) IF value = 0 THEN GOTO CopyFN char$ = CHR$(value) Pathname$ = Pathname$+char$ NEXT i CopyFN: Filename$ = "" 'Copy out the Filename to Filename$. FOR i = 0 TO 30 value = PEEK(FileIO+2+i) IF value = 0 THEN GOTO CopyDrawer char$ = CHR$(value) Filename$ = Filename$+char$ NEXT i CopyDrawer: 'Copy out all the drawers DrawerName$ = "" FOR i = 0 TO 132 value = PEEK(FileIO+32+i) IF value = 0 THEN GOTO CopyVol char$ = CHR$(value) DrawerName$ = DrawerName$+char$ NEXT i CopyVol: 'Copy out the diskname VolName$ = "" FOR i = 0 TO 30 value = PEEK(FileIO+164+i) IF value = 0 THEN GOTO PrintPath char$ = CHR$(value) VolName$ = VolName$+char$ NEXT i PrintPath: 'Print out all the info available in the FileIO LOCATE 7,1 noExt: CALL AutoMessage(SADD(Pathname$),WINDOW(7)) 'display our complete path in a 'requester first PRINT 'Let's print out the disk, drawers, and filename. PRINT "The Diskname is ",VolName$ PRINT "The Drawernames are ",DrawerName$ PRINT "The Filename is ",Filename$ 'Note that there is no Filename if the 'user selected only a disc or drawer. 'Let's get the amount of free disk space on the disk that the user chose. 'This could be important if we were trying to save something to this disk 'and there wasn't enough room. Also, if the user typed in a disc or drawer 'that didn't exist or he refused to place that disc in the drive, the 'returned default disc is ":" which is the current directory. PRINT "Free disk space: ",PEEKL(FileIO+236)," bytes." 'Now if this is a loadable file, the FileIO has it's size. If it's only a 'disc name or dir, or the file doesn't exist, then the size = 0. extsize=LEN(Filename$) 'Did the user finally select a file? IF extsize = 0 THEN GOTO DiscOrDir 'Must be a disk or drawer only IF PEEKL(FileIO+240) = 0 THEN GOTO NoExist 'Aha! User typed in a Filename that doesn't yet exist PRINT "Size of file: ",PEEKL(FileIO+240)," bytes." ' Now, you might want to do a load or save routine using this user selected ' pathname. You can check the FileIO's FILE.BYTESIZE (FileIO+240) field to see if the ' user actually selected an existing file, or typed in a new, non-existant ' name. For example, say that the user selected a directory but not a file ' within the directory. The returned pathname might be ' DF0:SomeDrawerName ' In this case, the FILE.BYTESIZE field would be 0 and if you tried to "load" ' the file, you would get a DOS error message. Likewise, if the user types ' in a non-existant file name, this field is also 0, but you can open the ' file for writing (save). If the user's selected pathname is the name of ' an object file (not just a dir or disk), then this is the only time that ' FILE.BYTESIZE will not be 0. In fact, it will be the size of the file. In ' conclusion, if you were doing a load routine, you would do the following ' steps at this point: ' 1). Check if there is some name in the FileIO's Filename field. If not, ' this means that the user selected a disk or drawer only. Abort the load. ' 2). Check to see if the FILE.BYTESIZE field is 0. If it is 0, then the ' user has typed in a file that doesn't exist (in whichever dir that he ' finally chose). Display a message that says "File doesn't exist". ' 3). If the FILE.BYTESIZE is not 0, then you can open the file for reading ' and copy this many bytes into memory. Since AmigaBasic doesn't have a ' facility for loading blocks of bytes, I recommend the DOS library. ' ' LIBRARY "dos.library" ' LIBRARY "intuition.library" ' DECLARE FUNCTION Open() LIBRARY ' DECLARE FUNCTION Read() LIBRARY ' DECLARE FUNCTION Write() LIBRARY ' Filehandle=Open(BufferPtr,1005&) ' IF Filehandle <> 0 THEN GOTO GotIt ' Message$ = "Cannot locate this file!"+CHR$(0) 'Oops Can't find it. ' CALL AutoMessageLen(SADD(Message$),WINDOW(7),24&) ' GOTO BadLoad 'GotIt: ' CALL SetWaitPointer(WINDOW(7)) ' Bytes=PEEKL(FileIO+240) ' DIM DataBuffer(Bytes) 'read the file into this 1-D array ' Result=Read(Filehandle,VARPTR(DataBuffer(0)),Bytes) ' CALL Close(Filehandle) ' CALL ClearPointer(WINDOW(7)) 'must have intuition open ' IF Result = Bytes THEN GOTO GoodLoad ' boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured ' GOTO BadLoad 'GoodLoad: ' You can now "pull out" data from DataBuffer as you need it (like we ' extracted data from FileIO except perhaps you might not want to ' convert the value to ascii via CHR$). ' If you were doing a save routine to disk, you would do the following: ' 1). Check if there is some name in the FileIO's Filename field. If not, ' this means that the user selected a disk or drawer only. Abort the save. ' 2). Check if FILE.BYTESIZE is not 0. If not 0, inform the user that this ' file already exists and if you save using this name, you will write ' over the other file. Ask the user if he wants to do the save anyway. ' 3). If FILE.BYTESIZE is 0, this file doesn't already exist. Check that the ' free disk space is greater than the number of bytes that we want to ' save, or else we'll run out of room during the save. ' ' Let's say that you stored the data in a big 1-D array called DataTank ' and the number of bytes you want to save is 32. ' ' Bytes=32& ' Filehandle=Open(BufferPtr,1006&) ' IF Filehandle <> 0 THEN GOTO CreateIt ' Message$ = "Cannot create the file!"+CHR$(0) 'Oops Can't save it. ' CALL AutoMessageLen(SADD(Message$),WINDOW(7),23&) ' GOTO BadSave ' CALL SetWaitPointer(WINDOW(7)) ' Result=Write(Filehandle,VARPTR(DataTank(0)),Bytes) ' CALL Close(Filehandle) ' CALL ClearPointer(WINDOW(7)) ' IF Result = Bytes THEN GOTO GoodSave ' boolean=AutoFileMessage(2&,WINDOW(7)) 'tell the user that an error occured ' GOTO BadSave 'GoodSave: Retry: message$ = "This has been a test of the FileIO library." + CHR$(0) Message2$ = "Do you want to retry?" + CHR$(0) boolean=AutoPrompt3(SADD(message$),SADD(Message2$),0,WINDOW(7)) CLS IF boolean = 1 THEN GOTO Again 'Note how the lib automatically spaces these messages symmetrically message$ = "Example program and asm lib by Jeff Glatt" + CHR$(0) Message2$ = "(dissidents)" + CHR$(0) Message3$ = "Original FileIO by RJ Mical" + CHR$(0) boolean=AutoPrompt3(SADD(message$),SADD(Message2$),SADD(Message3$),WINDOW(7)) CloseUp2: CALL ResetTitle(FileIO,WINDOW(7)) 'Maybe we changed it for the error msgs. CALL ReleaseFileIO(FileIO) 'Free the FileIO structure CloseUp1: CALL FreeMem(ExtPtr,BUFSIZE2) NoMem2: CALL FreeMem(BufferPtr,BUFSIZE) NoMem1: LIBRARY CLOSE END ' For these 2 errors, let's see how the SetTitle function works. This will ' display in the window's title bar string1 followed by string2, but unlike ' a requester, returns control back to the program. When we finally call ' ResetTitle, the original title is restored. We can call SetTitle without ' needing a ResetTitle inbetween and vica versa. Notice how this message ' appears in the window and requester title bars. Subsequent calls to these ' error routines (answer "Yes" to the again requester and cause another ' error) will change the title bar further. Yet, when we finally call ' ResetTitle upon exit, the initial title is restored. As you can see, these ' routines are good for posting error msgs that don't halt the program (like ' requesters) but remain visible for as long as they are needed. DiscOrDir: message$ = "Dir only - "+CHR$(0) 'String2 will be our Pathname CALL SetTitle(SADD(message$),SADD(Pathname$),FileIO,WINDOW(7)) GOTO Retry NoExist: message$ = "This file doesn't exist."+CHR$(0) 'Note how we indicate that we don't want String2. You must have string1 'though, even it were just a space. CALL SetTitle(SADD(message$),0,FileIO,WINDOW(7)) GOTO Retry